Skip to content

apollo_l1_gas_price,apollo_l1_gas_price_types: hold Chainlink query failures for the retry interval - #14992

Merged
asaf-sw merged 1 commit into
main-v0.14.3from
asaf/l1-oracle-a9b-negative-caching
Aug 21, 2026
Merged

asaf-sw merged 1 commit into
main-v0.14.3from
asaf/l1-oracle-a9b-negative-caching

Conversation

@asaf-sw

@asaf-sw asaf-sw commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Holds a failed Chainlink query's error in OracleState::last_error and spawns the next query once failure_retry_interval_seconds elapses rather than on every call. Without it, every fetch_rate against a broken feed spawns a fresh query, two view calls per feed per proposal, for as long as the feed stays broken.

A9b of the split of #14942, on top of the A9a lifecycle.


Detailed Summary for AI Bots

Stacked on #14991. Part of the L1 price oracle replacement split of #14942.

What

Negative caching for the Chainlink client: a failed query's error is held in OracleState::last_error and served to callers with nothing better, and the next query is spawned once failure_retry_interval_seconds elapses instead of on every call.

Why hold a failure

Without it, every fetch_rate against a failing feed spawns a fresh query: two view calls per feed per attempt, on every proposal, for as long as the feed stays broken. A hostile or broken feed would otherwise cost blocking VM executions per block. Holding the failure bounds the retry cadence to one query per retry interval, which is also why the interval is its own config key rather than the sampling interval: a transient failure costs one retry interval, not the rest of the sampling interval.

The precedence rule

A held failure is served only when no valid read is held. Bugbot's first review of #14942 caught an availability regression in exactly this spot: the one call that observed a failing query finish was returned that failure directly, without consulting the rate the client already held. no_call_is_denied_a_rate_the_client_holds is the regression test, asserting every call through the failure's harvest is served the held rate; a_held_failure_does_not_mask_the_last_valid_rate pins the steady state after the failure is held.

A success clears last_error, so the client never reports a failure older than its newest read.

Landing state

Testing

4 new tests (82 total). A failing feed is queried once per retry interval, with the batcher call counter flat across ten calls inside the interval; the retry fires exactly at the interval and not one second earlier; a held failure does not mask the last valid rate, including on the very call that harvests the failure.

🤖 Generated with Claude Code

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 09068b0 to a47b43d Compare August 18, 2026 20:57
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from c50e226 to c2af008 Compare August 18, 2026 20:57
@asaf-sw
asaf-sw marked this pull request as ready for review August 19, 2026 07:22
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from a47b43d to f9da995 Compare August 19, 2026 12:22
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from c2af008 to 8fafedf Compare August 19, 2026 12:22
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from f9da995 to ce31b09 Compare August 19, 2026 18:32
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 8fafedf to c9650d1 Compare August 19, 2026 18:32
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from ce31b09 to 2688157 Compare August 20, 2026 04:13
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from c9650d1 to 04688be Compare August 20, 2026 04:13
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 2688157 to e2d17a5 Compare August 20, 2026 04:43
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 04688be to 4715b2c Compare August 20, 2026 04:43
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from e2d17a5 to 57731b2 Compare August 20, 2026 06:37
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 4715b2c to 1e09207 Compare August 20, 2026 06:37
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 57731b2 to e1e1732 Compare August 20, 2026 07:11
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 1e09207 to 40c63d0 Compare August 20, 2026 07:11
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from b67ebe4 to fb3d2ed Compare August 20, 2026 11:03
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 888697e to 3df37d8 Compare August 20, 2026 11:03

@matanl-starkware matanl-starkware left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matanl-starkware reviewed 3 files and all commit messages, and made 2 comments.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on asaf-sw).


crates/apollo_l1_gas_price/src/chainlink_oracle/mod.rs line 236 at r1 (raw file):

        if let Some(valid_read) = state.last_valid_read {
            return Ok(valid_read.rate);
        }

Only within 3*interval timeout. Following PR?

Code quote:

        if let Some(valid_read) = state.last_valid_read {
            return Ok(valid_read.rate);
        }

crates/apollo_l1_gas_price/src/chainlink_oracle/mod.rs line 240 at r1 (raw file):

            Some(error) => Err(error),
            None => Err(ExchangeRateOracleClientError::QueryNotReadyError(block_timestamp)),
        }

Slightly nicer IMO.

Suggestion:

        match &state.last_error {
            Some(error) => Err(error.clone()),
            None => Err(ExchangeRateOracleClientError::QueryNotReadyError(block_timestamp)),
        }

@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 3df37d8 to 6f93b2f Compare August 20, 2026 11:33
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from fb3d2ed to 162b540 Compare August 20, 2026 11:33

@matanl-starkware matanl-starkware left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matanl-starkware made 1 comment and resolved 1 discussion.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on asaf-sw).


crates/apollo_l1_gas_price/src/chainlink_oracle/mod.rs line 236 at r1 (raw file):

Previously, matanl-starkware (Matan Lior) wrote…

Only within 3*interval timeout. Following PR?

Yeh, I see it there. 14993.

@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 162b540 to 6644123 Compare August 20, 2026 12:05
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 6f93b2f to 5389c40 Compare August 20, 2026 12:05
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 6644123 to 5809dfb Compare August 20, 2026 12:28
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 5389c40 to 0165fea Compare August 20, 2026 12:28
@asaf-sw

asaf-sw commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

crates/apollo_l1_gas_price/src/chainlink_oracle/mod.rs line 240 at r1 (raw file):

Previously, matanl-starkware (Matan Lior) wrote…

Slightly nicer IMO.

I agree.

@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 0165fea to 3140b1c Compare August 20, 2026 12:56

@asaf-sw asaf-sw left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asaf-sw+AGNT made 1 comment.
Reviewable status: 1 of 3 files reviewed, 1 unresolved discussion (waiting on matanl-starkware).


crates/apollo_l1_gas_price/src/chainlink_oracle/mod.rs line 240 at r1 (raw file):

Previously, asaf-sw wrote…

I agree.

Done, matching on a reference so nothing is cloned when there is no held error.

@matanl-starkware matanl-starkware left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matanl-starkware reviewed 2 files and all commit messages, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on asaf-sw).

@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9a-client-lifecycle branch from 5809dfb to dbe9769 Compare August 20, 2026 13:05
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 3140b1c to ba0f4e0 Compare August 20, 2026 13:05
@graphite-app
graphite-app Bot changed the base branch from asaf/l1-oracle-a9a-client-lifecycle to graphite-base/14992 August 20, 2026 17:55
@asaf-sw
asaf-sw force-pushed the graphite-base/14992 branch from dbe9769 to 1c10af6 Compare August 20, 2026 18:02
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from ba0f4e0 to 06a158a Compare August 20, 2026 18:03
@asaf-sw
asaf-sw changed the base branch from graphite-base/14992 to asaf/l1-oracle-a9a-client-lifecycle August 20, 2026 18:03
@asaf-sw
asaf-sw changed the base branch from asaf/l1-oracle-a9a-client-lifecycle to main-v0.14.3 August 20, 2026 18:27
@asaf-sw
asaf-sw force-pushed the asaf/l1-oracle-a9b-negative-caching branch from 06a158a to 881b0ab Compare August 20, 2026 18:27
@graphite-app

graphite-app Bot commented Aug 20, 2026

Copy link
Copy Markdown

Merge activity

  • Aug 20, 6:28 PM UTC: Graphite rebased this pull request, because this pull request is set to merge when ready.

@asaf-sw asaf-sw left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asaf-sw reviewed 3 files and all commit messages.
Reviewable status: 2 of 3 files reviewed, all discussions resolved (waiting on matanl-starkware).

@matanl-starkware matanl-starkware left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matanl-starkware reviewed 1 file and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on asaf-sw).

@asaf-sw
asaf-sw added this pull request to the merge queue Aug 21, 2026
Merged via the queue into main-v0.14.3 with commit 56f408d Aug 21, 2026
19 checks passed

Copy link
Copy Markdown
Contributor

Security scan complete — no issues detected.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants